package arkanoid.scenes;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

import arkanoid.components.Brick;
import arkanoid.components.Life;
import arkanoid.components.Palette;
import arkanoid.components.ball.Ball;
import arkanoid.components.ball.DisattachedNormalBall;
import arkanoid.components.ball.DisattachedStickyBall;
import arkanoid.components.powers.*;
import arkanoid.launcher.ArkanoidGame;

import com.uqbar.vainilla.GameScene;

public class Level extends GameScene {
	
	private Collection<Brick> bricks = new ArrayList<Brick>();
	private List<PowerUp> powers     = new ArrayList<PowerUp>();
	private Palette palette          = new Palette();
	private List<Ball> balls         = new ArrayList<Ball>();
	private List<Life> lifes         = new ArrayList<Life>();
	
	public static final int MAX_SPEED        = 300;
	public static final int MIN_SPEED        = 100;
	public static final int MAX_LONG_PALETTE = 100;
	public static final int MIN_LONG_PALETTE = 20;
	public static final int SPEED_CHANGE     = 20;
	public static final int PALETTE_CHANGE   = 20;
	
	public Level() {
		Ball mainBall = new Ball();
		this.getBalls().add(mainBall);
		this.addComponents(this.getPalette(), mainBall);
		this.setUpPowers();
	}

	private void setUpPowers() {
		for (int i = 0; i < 4; i++) {
			this.getPowers().add(new EnlargePalettePowerUp());
			this.getPowers().add(new SlowBallPowerUp());
			this.getPowers().add(new ReducePalettePowerUp());
			this.getPowers().add(new AccelerateBallPowerUp());
			this.getPowers().add(new MultiBallPowerUp());
			this.getPowers().add(new StickyBallPowerUp());
			this.getPowers().add(new LifeUpPowerUp());
			this.getPowers().add(new LevelDefeatedPowerUp());
		}
	}
	
	public void removeBrick(Brick brick) {
		this.getBricks().remove(brick);
		brick.destroy();
	}
	
	public void doLifeUp() {
		Life lastLife = this.getLifes().get(this.getLifes().size() - 1);
		Life newLife = new Life(lastLife.getX() - 10, lastLife.getY());
		this.getLifes().add(newLife);
		this.addComponent(newLife);
	}
	
	public void doLifeDown() {
		Life life = this.getLifes().get(this.getLifes().size() - 1);
		this.getLifes().remove(life);
		life.destroy();
		this.reanimate();
	}
	
	public void reanimate() {
		Ball ball = new Ball();
		ball.loadBallInitialized(this.getPalette());
		this.addBall(ball);
	}
	
	public void addPower(PowerUp power) {
		this.getPowers().add(power);
		this.addComponent(power);
	}
	
	private void addBall(Ball newBall) {
		this.getBalls().add(newBall);
		this.addComponent(newBall);
	}
	
	public void removeBall(Ball ball) {
		this.getBalls().remove(ball);
		ball.destroy();
	}
	
	public boolean allBricksVanished() {
		return this.getBricks().isEmpty();
	}
	
	public boolean allBallsDropped() {
		return this.getBalls().isEmpty();
	}
	
	public boolean allLifesWasted() {
		return this.getLifes().isEmpty();
	}
	
	public void reducePalette() {
		int paletteWidth = this.getPalette().getWidth();
		if (paletteWidth >= MIN_LONG_PALETTE) {
			this.getPalette().changeSize(paletteWidth - PALETTE_CHANGE, this.getPalette().getHeight());
		}
	}
	
	public void enlargePalette() {
		int paletteWidth = this.getPalette().getWidth();
		if (paletteWidth <= MAX_LONG_PALETTE) {
			this.getPalette().changeSize(paletteWidth + PALETTE_CHANGE, this.getPalette().getHeight());
		}
	}
	
	public void slowBall() {
		for (Ball ball : this.getBalls()) {
			int speed = ball.getSpeed();
			if (speed >= MIN_SPEED) {
				ball.setSpeed(speed - SPEED_CHANGE);
			}
		}
	}
	
	public void accelerateBall() {
		for (Ball ball : this.getBalls()) {
			int speed = ball.getSpeed();
			if (speed <= MAX_SPEED) {
				ball.setSpeed(speed + SPEED_CHANGE);
			}
		}
	}
	
	public void throwNewBall() {
		Ball newBall = new Ball();
		newBall.setState(new DisattachedNormalBall());
		newBall.setX(this.getPalette().getX() + this.getPalette().getWidth() / 2);
		newBall.setY(this.getPalette().getY() - newBall.getDiameter());
		newBall.setVersors(new Random());
		
		this.addBall(newBall);
	}
	
	public void dropPowerUp(double x, double y) {
		int next = (int)(Math.random() * this.getPowers().size());
		PowerUp randomPower = this.getPowers().get(next);
		
		if (randomPower.isAvailable()) {
			randomPower.setAvailable(false);
			this.addComponent(randomPower);
			randomPower.setX(x);
			randomPower.setY(y);
		}
	}
	
	public void turnStickys() {
		for (Ball ball : this.getBalls()) {
			int duration = (int)(40 + (Math.random() * (60 - 40) + 1));
			ball.setState(new DisattachedStickyBall(duration, ball));
		}
	}
	
	public void changeScene() {
		ArkanoidGame game = (ArkanoidGame) this.getGame();
		game.changeNextScene();
	}
	
	

	
	
	// ************************************************************
	// ** ACCESSORS
	// ************************************************************
	
	public Collection<Brick> getBricks() {
		return bricks;
	}

	public Palette getPalette() {
		return palette;
	}

	public void setPalette(Palette palette) {
		this.palette = palette;
	}

	public List<Ball> getBalls() {
		return balls;
	}

	public List<PowerUp> getPowers() {
		return powers;
	}

	public List<Life> getLifes() {
		return lifes;
	}

	public void setBricks(Collection<Brick> bricks) {
		this.bricks = bricks;
		this.addComponents(bricks);
	}

	public void setLifes(List<Life> lifes) {
		this.lifes = lifes;
		this.addComponents(lifes);
	}
}
